/*
 * Project: push-center-service-impl
 * 
 * File Created at 2014-10-9
 * 
 * Copyright 2012 Greenline.com Corporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * Greenline Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Greenline.com.
 */
package com.greenline.push.service.core.send;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.greenline.push.core.enums.Channels;
import com.greenline.push.core.enums.MsgSendType;
import com.greenline.push.core.enums.Tasks;
import com.greenline.push.core.pushcenter.GroupUserManager;
import com.greenline.push.service.core.item.AppPacket;
import com.greenline.push.service.core.item.Packet;
import com.greenline.push.service.core.send.base.AbstractSender;
import com.greenline.push.service.core.send.base.AppPacketHandler;
import com.greenline.push.service.core.tmpl.GroupAppCache;
import com.greenline.push.service.core.user.UserConnact;
import com.greenline.push.service.core.utils.Constants;
import com.greenline.push.service.core.utils.mail.MailService;

/**
 * 
 * @Type EmailSender
 * @Desc 发送email消息
 * @author shuai.zuo
 * @date 2014年10月28日
 * @Version V1.0
 */
public class EmailSender extends AbstractSender {
    @Autowired
    private MailService mailService;
    private static final String TEXT = "text";
    Logger log = Constants.LOG_PROCESS;
    @Autowired
    private GroupUserManager groupUserService;
    @Resource
    private GroupAppCache groupAppCache;
    @Resource
    private AppPacketHandler packetHandler;

    // private static final String HTML = "html";

    @Override
    public Channels supportChannel() {
        return Channels.email;
    }

    @Override
    protected boolean doSend(Packet packet) {
        AppPacket appPacket = (AppPacket) packet;
        log.info(String
                .format("{emailSender收到数据}:准备发送***domainId:[%s].tempId:[%s].recervId:[%s],type:[%s],context-token:[%s-%s],source:[%s],retryId:[%s],thread:[%s]",
                        appPacket.getDomainId(), appPacket.getTemplateId(), appPacket.getRecvUserId(), appPacket.getType(), appPacket
                                .getContext(), appPacket.getDeviceToken(), appPacket.getSource(), appPacket.getDbRetryId(), Thread
                                .currentThread().getName()));
        boolean result = false;
        try {
            if (MsgSendType.POINT.getType() == appPacket.getType()) {
                result = sendPoint(appPacket);
            } else if (MsgSendType.GROUP.getType() == appPacket.getType()) {
                sendGroup(appPacket);
            } else if (MsgSendType.UPLOAD.getType() == appPacket.getType() || MsgSendType.CONDITIONS.getType() == appPacket.getType()
                    || MsgSendType.DOMAIN.getType() == appPacket.getType()) {
                // upload 或者 condition 类型 可以调用第三方按组发送
                this.sendList(appPacket);
            } else {
                // sendGroup(appPacket);
                packetHandler.afterSendOperation(appPacket, false);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("[" + Thread.currentThread().getName() + "] Exception during packet processing: " + JSON.toJSONString(packet), e);
            packetHandler.afterSendOperation(appPacket, result, false);
        }
        // //下面是测试代码
        // result = true;
        // try {
        // Thread.sleep(800l);
        // super.afterSendOperation(appPacket, result);
        // } catch (InterruptedException e) {
        // e.printStackTrace();
        // }

        return result;
    }

    /**
     * call list
     * 
     * @param appPacket
     */
    private void sendList(AppPacket appPacket) {
        String methodName = "{emailSender.sendList}";
        Long retryId = appPacket.getDbRetryId();
        List<String> uids = getUserIdsByRetryId(retryId);
        // null case
        if (uids == null) {
            log.error(String.format("%s发送失败,apppacket下没有取到用户.retryId:[%s].context:[%s]", methodName, retryId, appPacket.getContext()));
            packetHandler.afterSendOperation(appPacket, false, true);
            return;
        }
        // set uid
        appPacket.setUserids(uids.toString());

        log.debug(String.format("%s批量发送email消息.uidlist:[%s].contenxt:[%s]", methodName, uids.toString(), appPacket.getContext()));
        List<String> emailList = new ArrayList<String>();
        for (int i = 0; i < uids.size(); i++) {
            Long uid = Long.valueOf(uids.get(i));
            UserConnact ucontact = getUserConnact(uid);
            if (ucontact == null || StringUtils.isBlank(ucontact.getEmail()))
                continue;
            // build email array
            emailList.add(ucontact.getEmail());
        }
        if (emailList.size() == 0) {
            log.warn(String.format("%s批量发送email消息获取到email列表为空,不再进行下一步处理.uidlist:[%s].contenxt:[%s]", methodName, uids.toString(),
                    appPacket.getExtParam()));
            // delete directly
            packetHandler.afterSendOperation(appPacket, false, true);
            return;
        }
        // move to string array
        String[] emails = new String[emailList.size()];
        emailList.toArray(emails);
        log.debug(String.format("%s开始批量发送.uids:[%s].emails:[%s],dbretryId:[%s]", methodName, uids.toString(), Arrays.toString(emails),
                appPacket.getDbRetryId()));
        boolean result = false;
        String extTemplatetype = appPacket.getExtTemplType();
        Map<String, String> param = appPacket.getExtParam();
        String templateName = appPacket.getExtTemplId();

        boolean isText = (null == extTemplatetype) ? false : extTemplatetype.equalsIgnoreCase(TEXT);
        result = mailService.send(templateName, emails, param, isText ? true : false);

        packetHandler.afterSendOperation(appPacket, result);

        log.info(String.format("%s发送完成.返回:[%s].emails:[%s].contenxt:[%s],retryId:[%s]", methodName, result, Arrays.toString(emails),
                appPacket.getExtParam(), appPacket.getDbRetryId()));
    }

    private boolean sendPoint(AppPacket appPacket) {
        String methodName = "{emailSender.sendPoint}";
        boolean result = false;
        String email = appPacket.getDeviceToken();
        String extTemplatetype = appPacket.getExtTemplType();
        Map<String, String> param = appPacket.getExtParam();
        String templateName = appPacket.getExtTemplId();

        boolean isText = (null == extTemplatetype) ? false : extTemplatetype.equalsIgnoreCase(TEXT);
        try {
            result = mailService.send(templateName, email, param, isText ? true : false);
            log.info(String.format("%s点对点推送结果: 返回 :[%s]. emails:[%s]. content:[%s],dbretryId:[%s]", methodName, result, email, param,
                    appPacket.getDbRetryId()));
        } catch (Exception e) {
            e.printStackTrace();
            result = false;
            log.error(String.format("%s点对点推送异常:errormsg:[%s]. packet:[%s],dbretryId:[%s]", methodName, e.getMessage(),
                    JSON.toJSONString(appPacket), appPacket.getDbRetryId()));
        }
        packetHandler.afterSendOperation(appPacket, result);
        return result;
    }

    private void sendGroup(AppPacket appPacket) {
        log.debug(String.format("{email**sendGroup开始推送}context:[%s],gid:[%s]", appPacket.getContext(), appPacket.getRecvUserId()));

        String relativeGroupId = groupAppCache.loadByGroupId(appPacket.getAppChannelId(), appPacket.getRecvUserId());
        if (StringUtils.isBlank(relativeGroupId)) {
            Long gid = appPacket.getRecvUserId();
            List<Long> userIds = getUserIdsbyGid(gid);
            for (Long userId : userIds) {
                // 转化成point
                UserConnact ucontact = getUserConnact(userId);
                if (ucontact == null)
                    continue;
                // send...
                appPacket.setRecvUserId(userId);
                appPacket.setDeviceToken(ucontact.getEmail());
                sendPoint(appPacket);
            }
        } else {
            // send group directly
            log.error(String.format("{email调用群发失败.}原因:[%s].gid:[%s],appchannelId:[%s]", "没有快捷群发接口", appPacket.getRecvUserId(),
                    appPacket.getAppChannelId()));
        }
    }

    @Override
    protected Tasks getTaskType() {
        return Tasks.FETCH_RETRY_EMAIL;
    }

    @Override
    protected String getQueueName() {
        return "邮件发送处理队列";
    }

    @Override
    protected Tasks getFullTaskType() {
        return Tasks.FETCH_RETRY_EMAIL_FULL;
    }

    @Override
    protected String getFullQueueName() {
        return "邮件全量发送处理队列";
    }

}
